# 自定义Django文件存储系统,不使用原来django系统自带的存储系统，使用fastfds更快。
# django自带文件存储系统，但默认文件存储在本地，在本项目中，我们需要将文件保存到FastDFS服务器上。
# 所以需要自定义文件存储系统


# 1.您的自定义存储系统必须是以下子类 django.core.files.storage.Storage：
from django.core.files.storage import Storage
from fdfs_client.client import Fdfs_client
from mall import settings
from django.utils.deconstruct import deconstructible
# 您的存储类必须是可解构的， 以便在迁移中的字段上使用时可以对其进行序列化。
# 只要您的字段具有可自行序列化的参数，
# 就 可以使用 django.utils.deconstruct.deconstructible类装饰器
# （这就是Django在FileSystemStorage上使用的）
# 需要为存储类添加django.utils.deconstruct.deconstructible装饰器


@deconstructible
class FastDFSStorage(Storage):
    # 2.Django必须能够在没有任何参数的情况下实例化您的存储系统。
    # 这意味着任何设置都应该来自django.conf.settings,需要有init方法，不需要传参数
    def __init__(self,path=None,ip=None):
        if path is None:
            path = settings.FDFS_CLIENT_CONF
            self.config_path = path
        if ip is None:
            ip = settings.FDFS_URL
            self.ip = ip


    # 3.您的存储类必须实现_open()和_save()方法以及适用于您的存储类的任何其他方法。
    # _open()打开图片，我们采用的是fastDFS服务器是通过http来打开图片的（访问的），不需要打开的方法
    def _open(self, name, mode='rb'):
        pass
    # 保存
    # 需要有保存的功能，就是上传到fastDFS服务器

    def _save(self, name, content, max_length=None):
        # name:只是一个文件名，并不是一个路径
        # content:是上传的内容，可以通过content.read()来获取文件的二进制数据

        # 1.先创建fastDFS客户端,加载配置文件那
        # client = Fdfs_client('utils/fastdfs/client.conf')
        client = Fdfs_client(self.config_path)
        # 获取文件，读取图片为二进制
        file_data = content.read() # 获取文件的二进制数据

        # 3.上传图片
        # buffer会上传二进制数据，并把结果返回
        result = client.upload_by_buffer(file_data)
        """
        {'Local file name': '/home/python/Desktop/111.jpg',
        'Status': 'Upload successed.',
         'Storage IP': '192.168.76.129',
          'Group name': 'group1',
          'Uploaded size': '10.00KB',
         'Remote file_id': 'group1/M00/00/00/wKhMgVtoAqaAJxoGAAAomgYzrKs963.jpg'}
        """
        # 4.判断返回状态
        if result.get('Status') == 'Upload successed.':
            return result.get('Remote file_id')
        else:
            raise Exception('上传失败')


    # 还有额外要实现的两个方法
    # 判断文件是否存在，fastDFS会对文件做重名处理，
    # 所以同一文件上传很多次也没有问题
    def exists(self, name):
        return False
    # 获取文件路径
    def url(self, name):
        # name就是返回的那个Remote file_id
        # group1/M00/00/00/wKhMgVtoAqaAJxoGAAAomgYzrKs963.jpg
        # 获取文件路径如果只返回一个Remote file_id的话，需要再添加tacker的id和port
        # 所以直接拼接好图片的url返回

        # return 'http://192.168.76.129:8888'+ name
        return self.ip + name

